package com.rankeiot.demo;

import com.github.benmanes.caffeine.cache.CacheLoader;
import com.rankeiot.core.MenuManager;
import com.rankeiot.core.anno.Menu;
import com.rankeiot.core.anno.Permission;
import com.rankeiot.core.data.MenuItem;
import com.rankeiot.platform.PlatformApplication;
import com.rankeiot.platform.PlatformMenu;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.cache.support.NoOpCache;
import org.springframework.context.*;
import org.springframework.context.annotation.*;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;




@SpringBootApplication
//@Configuration
//@EnableAsync
//@Import(DemoApp.SubDefine.class)
public class DemoApp  implements ApplicationContextInitializer {

    @Override
    public void initialize(ConfigurableApplicationContext ctx) {
//        GenericApplicationContext context=(GenericApplicationContext)ctx;
//            context.registerBean("testCache",Cache.class,()->{
//                CacheManager cacheManager= ctx.getBean(CacheManager.class);
//                return cacheManager.getCache("default");
//            });
//
    }
//    @Bean
//    CacheManagerCustomizer<CaffeineCacheManager> cacheManagerCustomizer(){
//        return  new CacheManagerCustomizer<CaffeineCacheManager>() {
//            @Override
//            public void customize(CaffeineCacheManager cacheManager) {
//                cacheManager.
//            }
//        };
//    }
    @Bean
    @ConditionalOnMissingBean(value = CacheManager.class)
    CacheLoader cacheLoader(){
        return new CacheLoader() {
            @Override
            public Object load(Object key) throws Exception {
                return null;
            }

            @Override
            public Object reload(Object key,Object oldValue) throws Exception {
                return oldValue;
            }
        };
    }

    static class SubDefine implements ImportBeanDefinitionRegistrar {

        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//            GenericBeanDefinition bd=new GenericBeanDefinition();
//            bd.setPrimary(true);
//           // bd.setBeanClass(Cache.class);
//
//            bd.setSource(new NoOpCache("primary"));
//            registry.registerBeanDefinition("testCache",bd);
//            ApplicationEvent
//            // bd.setFactoryMethodName();
//            context.registerBean("testCache",Cache.class,()->{
//                return new NoOpCache("primary");
//            });
            GenericBeanDefinition bd=new GenericBeanDefinition();
            //registry.registerBeanDefinition();
            bd.setSource(new NoOpCache("primary"));
            bd.setBeanClass(Cache.class);
            bd.setAbstract(true);

            // bd.setPrimary(true);
            registry.registerBeanDefinition("test",bd);
        }


        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            GenericBeanDefinition bd=new GenericBeanDefinition();
            //registry.registerBeanDefinition();
            bd.setSource(new NoOpCache("primary"));
            bd.setBeanClass(Cache.class);
            bd.setAbstract(true);

           // bd.setPrimary(true);
            registry.registerBeanDefinition("test",bd);

        }

//        @Override
//        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//            Cache cache= (Cache) configurableListableBeanFactory.getBean("test");
//            System.out.println(cache);
//        }
    }

    public static void main(String[] args) {
       // MenuManager.addMenu(new MenuItem("test","测试","test.vue"));//.regMenu(new MenuItem());

       // MenuManager.addMenu(new MenuItem("test1","表格测试","dataTableTest.vue"));//.regMenu(new MenuItem());
       MenuManager.regMenu(TestMenu.class);
      // SpringApplication.run(DemoApp.class,args);
      //  new PlatformApplication().start(args);
        PlatformApplication.run(args);
    }

    @Menu(value = "测试", icon = "icon-cog", id = TestMenu.ID)
    public  interface TestMenu{
        String ID="test";
        @Menu(value = "测试菜单", icon = "icon-menu")
        String MENU_TEST=ID+".menu";
        @Menu(value = "表格测试", icon = "icon-grid-2",path = "dataTableTest.vue",parent=MENU_TEST)
        String GRID_TEST=MENU_TEST+".test";
        @Permission(value = "表格测试-添加权限",parent=GRID_TEST)
        String GRID_TEST_ADD=MENU_TEST+".test.add";
        @Menu(value = "其他", icon = "icon-grid-2",path = "dataTableTest.vue",parent=MENU_TEST)
        String OTHER_TEST=MENU_TEST+".other";
       // icon-grid-2
       @Menu(value = "测试菜单", icon = "icon-menu",path = "test.vue")
       String MENU_TEST_2=ID+".menu2";
    }
}
